<?php
/**
 * 遍历树结构,获取其中某项元素的值
 * 用法
 *  $menu = include(APP_PATH .'Common/Conf/menu.php');
    $list = tree_get_value($menu, 'name');  //返回name一维数组
 *  $list = tree_get_value($menu);  //返回二维维数组
 *
 *
 * @param $tree     树结构
 * @param $getKey   元素名
 * @param string $childKey  子元素key
 * @author linshiling
 */
function tree_to_array($tree, $getKey = '', $childKey = 'subs')
{
    $list = array();
    foreach ($tree as $item) {
        $subs = $item[$childKey];
        unset($item[$childKey]);
        $list[] = $getKey ? $item[$getKey] : $item;
        if($subs) {
            $subList = tree_to_array($subs, $getKey, $childKey);
            $list = array_merge($list, $subList);
        }
    }
    $list = array_filter($list);
    $list = array_values($list);    //key重新排序,否则json_encode时会变成对象而不是数组
    return $list;
}


/**
 * 把返回的数据集转换成Tree
 * @param array $list 要转换的数据集
 * @param string $pk
 * @param string $pid parent标记字段
 * @param string $child 子数组标记
 * @param int $root
 * @return array
 */
function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = '_sub', $root = 0)
{
	// 创建Tree
	$tree = array();
	if (is_array($list)) {
		// 创建基于主键的数组引用
		$refer = array();
		foreach ($list as $key => $data) {
			$refer[$data[$pk]] =& $list[$key];
		}
		foreach ($list as $key => $data) {
			// 判断是否存在parent
			$parentId = $data[$pid];
			if ($root == $parentId) {
				$tree[] =& $list[$key];
			} else {
				if (isset($refer[$parentId])) {
					$parent           =& $refer[$parentId];
					$parent[$child][] =& $list[$key];
				}
			}
		}
	}
	return $tree;
}

/**
 * 将list_to_tree的树还原成列表
 * @param  array $tree 原来的树
 * @param  string $child 孩子节点的键
 * @param  string $order 排序显示的键，一般是主键 升序排列
 * @param  array $list 过渡用的中间数组，
 * @return array        返回排过序的列表数组
 */
function tree_to_list($tree, $child = '_sub', $order = 'id', &$list = array())
{
	if (is_array($tree)) {
		$refer = array();
		foreach ($tree as $key => $value) {
			$reffer = $value;
			$list[] = $reffer;
			if (isset($reffer[$child])) {
				tree_to_list($value[$child], $child, $order, $list);
			}
		}
	}
	foreach($list as &$l) {
		if($l[$child]) {
			unset($l[$child]);
			$l['has_sub'] = true;
		}
	}
	return $list;
}

/**
 * 将2维数组转为1维映射数组
 * $map = array_to_map($data, 'name', 'api');   //array('user' => '/user/ls', 'resume' => '/resume/delete');
 *
 * @param $data     2维数组
 * @param $key      映射数组的key
 * @param $value    映射数组的value
 * @return array
 */
function array_to_map($data, $key, $value)
{
    $array = array();
    foreach($data as $item) {
        $item[$key] && $array[$item[$key]] = $item[$value];
    }
    $array = array_filter($array);
    return $array;
}

/**
 * 把多维数组转化成一维数组
 *
 * @param array $arr 需要转换的数组，必须有相同的子节点
 * @param string $sub 子节点名称
 * @param array &$rs 返回的引用数组
 *
 * @return array|bool
 */
function floatArray($arr = array(), $sub = '_sub', &$rs)
{
    if (empty($arr)) {
        return false;
    }
    foreach ($arr as $v) {
        $tmp2 = $v;
        if (isset($tmp2[$sub])) {
            unset($tmp2[$sub]);
            $rs[] = $tmp2;
            floatArray($v[$sub], $sub, $rs);
        } else {
            $rs[] = $v;
        }
    }
}

/**
 * 获取指定的键值
 *
 * @param    array
 * @param    string
 *
 * @return   array
 */
function getSingleKey($array, $key)
{
    $infos = array();
    if (empty($array)) {
        return $infos;
    }
    foreach ($array as $val) {
        isset($val[$key]) && $infos[] = $val[$key];
    }

    return $infos;
}

/**
 * 按照key组合数组
 *
 * @param    array
 * @param    string
 *
 * @return   array
 **/
function singleGroup($array, $key)
{
    if (empty($array)) {
        return array();
    }

    $array1 = array();

    foreach ($array as $val) {
        $array1[$val[$key]] = $val;
    }

    return $array1;
}

//_mkDir
function _mkDir($dir, $mode = 0777)
{
    if (!is_dir($dir)) {
        _mkDir(dirname($dir), $mode);
        $old = umask(0);
        @mkdir($dir, $mode);
        umask($old);
        return true;
    }
    return true;
}

//_delDir
function _rmDir($dir)
{
    if (!is_dir($dir)) {
        return false;
    }
    $dh = opendir($dir);
    while ($file = readdir($dh)) {
        if ($file != "." && $file != "..") {
            $fullpath = $dir . "/" . $file;
            if (!is_dir($fullpath)) {
                unlink($fullpath);
            } else {
                _rmDir($fullpath);
            }
        }
    }
    closedir($dh);
    if (_rmDir($dir)) {
        return true;
    } else {
        return false;
    }
}

/*
 * 删除指定目录中的所有目录
 * 可扩展增加一些选项（如是否删除原目录等）
 * 删除文件敏感操作谨慎使用
 * @param $dir 目录路径
 * @param array $file_type指定文件类型
 */
function delFile($dir, $file_type = '')
{
    if (!is_dir($dir)) {
        return false;
    }
    $files = scandir($dir);
    foreach ($files as $filename) {
        if ($filename != '.' && $filename != '..') {
            $fullpath = $dir . "/" . $filename;
            if (!is_dir($fullpath)) {
                if (empty($file_type)) {
                    unlink($fullpath);
                } else {
                    if (is_array($file_type)) {
                        //正则匹配指定文件
                        if (preg_match($file_type[0], $filename)) {
                            unlink($fullpath);
                        }
                    } else {
                        //指定包含某些字符串的文件
                        if (false != stristr($filename, $file_type)) {
                            unlink($fullpath);
                        }
                    }
                }
            } else {
                delFile($fullpath);
                rmdir($fullpath);
            }
        }
    }
}

//判断是否为email
function isEmail($str)
{
    return (filter_var($str, FILTER_VALIDATE_EMAIL) === false) ? false : true;
}

//手机
function isMobile($string)
{
    return preg_match('/^1[345678]+\d{9}$/', $string);
}

//随机字符
function randStr($len = 6, $type = 3, $addChars = null)
{
    $str = '';
    switch ($type) {
        case 1:
            $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' . $addChars;
            break;
        case 2:
            $chars = str_repeat('0123456789', 3);
            break;
        case 3:
            $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . $addChars;
            break;
        case 4:
            $chars = 'abcdefghijklmnopqrstuvwxyz' . $addChars;
            break;
        default :
            $chars = 'ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789' . $addChars;
            break;
    }
    if ($len > 10) {
        $len = 10;
    }
    $charLen = strlen($chars) - 1;
    for ($i = 0; $i < $len; $i++) {
        $str .= $chars[mt_rand(0, $charLen)];
    }
    return $str;
}

//文件后缀名
function fileExt($filename, $scope = 10)
{
    return strtolower(trim(substr(strrchr($filename, '.'), 1, $scope)));
}

/**
 * 字符串截取，支持中文和其他编码
 *
 * @param string $str 需要转换的字符串
 * @param int $start 开始位置
 * @param string $length 截取长度
 * @param string $charset 编码格式
 * @param boolean $suffix 截断显示字符
 *
 * @return string
 */
function mSubStr($str, $start = 0, $length, $charset = "utf-8", $suffix = true)
{
    if (function_exists("mb_substr"))
        $slice = mb_substr($str, $start, $length, $charset);
    elseif (function_exists('iconv_substr')) {
        $slice = iconv_substr($str, $start, $length, $charset);
        if (false === $slice) {
            $slice = '';
        }
    } else {
        $re['utf-8']  = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
        $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
        $re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
        $re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
        preg_match_all($re[$charset], $str, $match);
        $slice = join("", array_slice($match[0], $start, $length));
    }
    $str_len = mb_strlen($str, 'utf-8');
    return ($suffix && $str_len > $length) ? $slice . '...' : $slice;
}

/**
 * 处理头像路径
 *
 * @param string $avatar
 * @param int $gender
 * @param boolean $with_http
 *
 * @return string
 */
function getHttpAvatar($avatar = '', $gender = 1, $with_http = true)
{
    $gender = intval($gender);
    if (!in_array($gender, array(0, 1))) {
        $gender = 1;
    }
    $male   = '/img/member/avatar_man.gif';
    $female = '/img/member/avatar_woman.gif';

    $avatar = trim($avatar);
    if ($avatar == '') {
        if ($gender === 0) {
            $avatar = $female;
        } else {
            $avatar = $male;
        }
        return $with_http ? HTTP_HTTPS . 'om.' . DOMAIN . $avatar : $avatar;
    }

    if (!is_file($_SERVER['DOCUMENT_ROOT'] . $avatar)) {
        if (DOMAIN != 'i-sanger.cn') {
            //测试环境下直接读取正式环境的头像
            return 'http://www.i-sanger.cn' . $avatar;
        } else {
            if ($gender === 0) {
                $avatar = $female;
            } else {
                $avatar = $male;
            }
        }
    }
    //加上http和域名
    return $with_http ? HTTP_HTTPS . 'om.' . DOMAIN . $avatar : $avatar;
}

/**
 * 用常规方式发送邮件
 *
 * @param string $to
 * @param string $subject
 * @param string $body
 * @param string $name
 * @param array $attachment
 *
 * @return mixed
 */
function send_mail_now($to = null, $subject = '', $body = '', $name = '', $attachment = null, $file_name = null)
{
    $from_email  = C('EMAIL_SMTP_USERNAME');
    $from_name   = C('PAGE_TITLE');
    $reply_email = C('EMAIL_POP_USERNAME');
    $reply_name  = '美吉生物';
    require_once('../Common/Tool/PHPMailer/phpmailer.class.php');
    $mail          = new PHPMailer; //实例化PHPMailer
    $mail->CharSet = 'UTF-8'; //设定邮件编码，默认ISO-8859-1，如果发中文此项必须设置，否则乱码
    $mail->IsSMTP(); // 设定使用SMTP服务
    $mail->SMTPDebug = 0; // 关闭SMTP调试功能
    // 1 = errors and messages
    // 2 = messages only
    $mail->SMTPAuth   = true; // 启用 SMTP 验证功能
    $mail->SMTPSecure = ''; // 使用安全协议
    $mail->Host       = C('EMAIL_SMTP_ADDRESS'); // SMTP 服务器
    $mail->Port       = C('EMAIL_SMTP_PORT'); // SMTP服务器的端口号
    $mail->Username   = C('EMAIL_SMTP_USERNAME'); // SMTP服务器用户名
    $mail->Password   = C('EMAIL_SMTP_PASSWORD'); // SMTP服务器密码
    $mail->SetFrom($from_email, $from_name);
    $replyEmail = $reply_email ? $reply_email : $from_email;
    $replyName  = $reply_name ? $reply_name : $from_name;
    $rec        = array();//接收人s
    if (empty($to)) {
        return '缺少收件人';
        //$rec[] = C('EMAIL_SMTP_USERNAME'); //邮件地址为空时，默认使用后台默认邮件测试地址
    }
    if (is_string($to)) {
        if (isEmail($to)) {
            $rec[] = $to;
        }
    }
    if (is_array($to)) {
        foreach ($to as $tt) {
            if (isEmail($tt)) {
                $rec[] = $tt;
            }
        }
    }
    if ($name == '') {
        $name = C('PAGE_TITLE'); //发送者名称为空时，默认使用网站名称
    }
    if ($subject == '') {
        $subject = C('PAGE_TITLE'); //邮件主题为空时，默认使用网站标题
    }
    if ($body == '') {
        $body = C('PAGE_TITLE'); //邮件内容为空时，默认使用网站描述
    }
    $mail->AddReplyTo($replyEmail, $replyName);
    $mail->Subject = $subject;
    $mail->MsgHTML($body); //解析
    foreach ($rec as $_to) {
        $mail->AddAddress($_to, $name);
    }
    if (is_array($attachment)) { // 添加附件
        foreach ($attachment as $file) {
            is_file($file) && $mail->AddAttachment($file, $file_name);
        }
    }
    return $mail->Send() ? true : $mail->ErrorInfo; //返回错误信息
}

/**
 * 读取excel成二维数组
 *
 * @param string $xls_path 表格路径
 * @param array $sheets 需要读取哪几个sheet,默认第一个0
 * @param string $type 驱动 (Excel5读取xls   |   Excel2007读取xlsx)
 *
 * @return mixed
 */
function readExcelToArray($xls_path = '', $sheets = array(0), $type = 'Excel5')
{
    $xls_path = trim($xls_path);
    if (!is_file($xls_path)) {
        return false;
    }
    if (empty($sheets)) {
        return false;
    }
    //打开表格
    import('IOFactory', COMMON_PATH . 'Tool/PHPExcel/PHPExcel/', '.php');
    $reader = \PHPExcel_IOFactory::createReader($type);
    $obj    = $reader->load($xls_path);

    foreach ($sheets as $s) {
        $datas['sheet_' . $s] = $obj->getSheet($s)->toArray();
    }
    return $datas;
}

/**
 * 由二维数组生成xls，并下载
 *
 * @param array $datas 数据
 * @param string $save_name 保存名称
 * @param string $type 驱动 (Excel5生成xls   |   Excel2007生成xlsx)
 * @param array $cell_color array( array('cell'=>'A1', 'color'=>'F28A8C') )
 *
 * @return void
 */
function outputExcelFromArray($datas = array(), $save_name = '', $type = 'Excel5', $cell_color = array())
{
    if (empty($datas)) {
        return;
    }
    $save_name = trim($save_name);
    if ($save_name == '') {
        $save_name = date('Y-m-d_H-i');
    }
    //导入PHPExcel
    import('PHPExcel', COMMON_PATH . 'Tool/PHPExcel/', '.php');

    // Create new PHPExcel object
    $objPHPExcel = new \PHPExcel();

    // Set document properties
    $objPHPExcel->getProperties()->setCreator("major")
        ->setLastModifiedBy("major")
        ->setTitle("Document")
        ->setSubject("Document")
        ->setDescription("major")
        ->setKeywords("major")
        ->setCategory("major");

    $objPHPExcel->setActiveSheetIndex(0);

    $objPHPExcel->getActiveSheet()->fromArray($datas);

    //设置背景颜色
    if (!empty($cell_color)) {
        foreach ($cell_color as $cc) {
            $cc['cell']  = trim($cc['cell']);
            $cc['color'] = trim($cc['color']);
            if ($cc['cell'] == '' && $cc['color'] == '') {
                continue;
            }
            $objPHPExcel->getActiveSheet()->getStyle($cc['cell'])->getFill()->applyFromArray(array(
                'type'       => PHPExcel_Style_Fill::FILL_SOLID,
                'startcolor' => array(
                    'rgb' => $cc['color']
                )
            ));
        }
    }

    $objPHPExcel->getActiveSheet()->setTitle($save_name);

    $hz = ($type == 'Excel2007') ? 'xlsx' : 'xls';

    ob_end_clean();
    // Redirect output to a client’s web browser (Excel5)
    header('Content-Type: application/vnd.ms-excel');
    header('Content-Disposition: attachment;filename="' . $save_name . '.' . $hz . '"');
    header('Cache-Control: max-age=0');
    // If you're serving to IE 9, then the following may be needed
    header('Cache-Control: max-age=1');
    // If you're serving to IE over SSL, then the following may be needed
    header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
    header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
    header('Pragma: public'); // HTTP/1.0

    $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, $type);
    $objWriter->save('php://output');
    exit;
}

/**
 * 由二维数组生成xls，并下载
 *
 * @param array $sheets = array(array(...), array(...), ..., =>array(...))
 * @param string $save_name 保存名称
 * @param string $driver 驱动 (Excel5生成xls   |   Excel2007生成xlsx)
 *
 * @return void
 */
function outputExcelMultiSheetFromArray($sheets = array(), $save_name = '', $driver = 'Excel2007')
{
    if (empty($sheets)) {
        return;
    }
    $save_name = trim($save_name);
    if ($save_name == '') {
        $save_name = date('Y-m-d_H-i');
    }
    //导入PHPExcel
    import('PHPExcel', COMMON_PATH . 'Tool/PHPExcel/', '.php');

    // Create new PHPExcel object
    $objPHPExcel = new \PHPExcel();

    // Set document properties
    $objPHPExcel->getProperties()->setCreator("major")
        ->setLastModifiedBy("major")
        ->setTitle("Document")
        ->setSubject("Document")
        ->setDescription("major")
        ->setKeywords("major")
        ->setCategory("major");

    $ki = 0;
    foreach ($sheets as $sheet) {
        if ($ki > 0) {
            $objPHPExcel->createSheet($ki);
        }
        $objPHPExcel->setActiveSheetIndex($ki);
        $objPHPExcel->getActiveSheet()->fromArray($sheet);
        $ki++;
        $objPHPExcel->getActiveSheet()->setTitle("sheet" . $ki);
    }

    $hz = ($driver === 'Excel2007') ? 'xlsx' : 'xls';

    ob_end_clean();
    // Redirect output to a client’s web browser (Excel5)
    header('Content-Type: application/vnd.ms-excel');
    header('Content-Disposition: attachment;filename="' . $save_name . '.' . $hz . '"');
    header('Cache-Control: max-age=0');
    // If you're serving to IE 9, then the following may be needed
    header('Cache-Control: max-age=1');
    // If you're serving to IE over SSL, then the following may be needed
    header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
    header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
    header('Pragma: public'); // HTTP/1.0

    $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, $driver);
    $objWriter->save('php://output');
    exit;
}

//跨子域名存储登录信息
function cdSession($name = null, $value = '')
{
    $space = 'scm'; //cross domains 跨子域名
    if ($name === '') {//没有key
        return null;
    }
    if (is_null($name)) {//清空
        unset($_SESSION[$space]);
    } else {
        if ($value === '') {//取值
            return isset($_SESSION[$space][$name]) ? $_SESSION[$space][$name] : null;
        } elseif ($value === null) {//销毁变量
            unset($_SESSION[$space][$name]);
        } else {//赋值
            $_SESSION[$space][$name] = $value;
        }
    }
    return null;
}

//返回json数据
function json($state, $msg = '')
{
    $ajax = 0;

    if (strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false) {
        $ajax = 1;    //html5上传
    }else if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
        $ajax = 1;    //ajax
    }else if (isset($_SERVER['HTTP_ORIGIN'])) {
        $ajax = 1;    //跨域ajax请求
    }else if (stripos($_SERVER['HTTP_USER_AGENT'], 'flash')) {
        $ajax = 1;    //flash请求
    }else if ($_GET['ajax']) {
        $ajax = 1;    //指明是ajax请求
    }else if(strpos($_SERVER['CONTENT_TYPE'], 'application/json') !== false) {
		$ajax = 1;		//edge
	}else if(strpos($_SERVER['HTTP_ACCEPT'], 'application/json') !== false) {
		$ajax = 1;		//edge
	}


    if (is_array($state)) {
        $data = $state;
    } else {
        if(is_string($msg)) {
            $data = array('st' => $state, 'msg' => $msg);
        }else{
            $data = array('st' => $state, 'data' => $msg);
        }
    }
    if ($ajax) {
        echo json_encode($data, JSON_UNESCAPED_UNICODE);
    } else {
        echo '<pre>';
        print_r($data);
        echo '</pre>';
    }
    exit;
}


/**
 * 用curl发送post请求,有文本格式和键值对模式两种
 * 键值对模式即表单模式,PHP会自动产生键值对
 * 文本格式通常用于传递json编码的数据
 * @param string $url
 * @param array $data
 * @param string $mod 传送post模式或json模式
 */
function curl_post($url, $data, $mod = 'post')
{
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    if ($mod == 'json') {
        //设置请求头为纯文本格式,一般用于与其他语言的通讯中直接传递json,不会创建post数组
        $headers[] = 'Content-Type: text/xml;charset=utf-8';
        $data      = json_encode($data, JSON_UNESCAPED_UNICODE);
    } else {
        //post模式.更适合与PHP通讯,可用$_POST接收
        $headers[] = 'Content-Type: application/x-www-form-urlencoded;charset=utf-8';
        $data      = http_build_query($data);
    }
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($curl, CURLOPT_HEADER, false);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_NOBODY, true);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    $return_str = curl_exec($curl);
    curl_close($curl);
    return $return_str;

}


/**
 * 发送手机短信
 */

function send_sms($mobile = '', $content = '')
{
    $url       = "http://sms.106jiekou.com/utf8/sms.aspx";
    $post_data = "account=lei.zhang&password=sg_sms_201414&mobile=" . $mobile . "&content=" . rawurlencode($content);
    $curl      = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_HEADER, false);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_NOBODY, true);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
    $return_str = curl_exec($curl);
    curl_close($curl);
    //短信返回结果信息
    $status = array(
        '100' => '发送成功',
        '101' => '验证失败',
        '102' => '手机号码格式不正确',
        '103' => '会员级别不够',
        '104' => '内容未审核',
        '105' => '内容过多',
        '106' => '账户余额不足',
        '107' => 'Ip受限',
        '108' => '手机号码发送太频繁，请换号或隔天再发',
        '109' => '帐号被锁定',
        '110' => '手机号发送频率持续过高，黑名单屏蔽数日',
        '120' => '系统升级',
    );
    if ($return_str == '100') {
        return array('code' => 'ok', 'msg' => $status[$return_str]);
    } else {
        return array('code' => 'err', 'msg' => $status[$return_str]);
    }
}

/**
 * 时间友好显示
 *
 * @param int $time
 */
function time2str($time)
{
    if (!$time) return '';
    if ($time > strtotime('today')) {
        return date('H:i:s', $time);
    }
    if ($time > strtotime('yesterday')) {
        return '昨天 ' . date('H:i');
    }
    if ($time > strtotime('last Monday')) {
        $map = array('日', '一', '二', '三', '四', '五', '六');
        $w   = date('w', $time);
        return '周' . $map[$w] . ' ' . date('H:i');
    }
    if (date('Y') == date('Y', $time)) {
        return date('m月d日', $time) . ' ' . date('H:i');
    }
    return date('Y-m-d', $time);;
}

//M()->query();之后取一个字段
function getOne($sql)
{
    $rs = M()->query($sql);
    return current($rs[0]);
}

//M()->query();之后取一条记录
function getRow($sql)
{
    $rs = M()->query($sql);
    return $rs[0];
}

//取一列
function getCol($sql, $mod = 'array')
{
    $rs = M()->query($sql);
    foreach ($rs as &$r) {
        $r = current($r);
    }
    return $mod == 'array' ? $rs : implode(',', $rs);
}

function getMap($sql)
{
    $rs  = M()->query($sql);
    $arr = array();
    foreach ($rs as $r) {
        $k       = current($r);
        $v       = array_pop($r);
        $arr[$k] = $v;
    }
    return $arr;
}

//获取客户端IP
function get_ip()
{
    if (getenv('HTTP_CLIENT_IP')) {
        $ip = getenv('HTTP_CLIENT_IP');
    } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
        $ip = getenv('HTTP_X_FORWARDED_FOR');
    } elseif (getenv('HTTP_X_FORWARDED')) {
        $ip = getenv('HTTP_X_FORWARDED');
    } elseif (getenv('HTTP_FORWARDED_FOR')) {
        $ip = getenv('HTTP_FORWARDED_FOR');

    } elseif (getenv('HTTP_FORWARDED')) {
        $ip = getenv('HTTP_FORWARDED');
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    return $ip;

}

//获取分类名
function getCate($id)
{
    static $map;
    if (!$map) {
        $map = getMap("SELECT id, title FROM cate");
    }
    $name = $map[$id];
    return $name ? $name : "无此分类：$id";
}

//id转姓名
function getAdmin($id)
{
    static $map;
    if (!$map) {
        $map = getMap("SELECT id, name FROM admin");
    }
    return $map[$id];
}

//姓名+部门名称转id,带缓存
function member_id($real_name, $dep_id)
{
    $sql = "SELECT id FROM member WHERE real_name = '$real_name' && (department_id = $dep_id || real_dep_id = $dep_id)";
    $id = getOne($sql);
    if(!$id) {
        $sql = "SELECT id FROM member WHERE real_name = '$real_name'";
        $id = getOne($sql);
    }
    return $id ? $id : 0;
}

//job_id转名称,带缓存
function jobName($id)
{
    static $map;
    if (!$map) {
        $map = getMap("SELECT id, job FROM hr_jobs");
    }
    return $map[$id];
}

//rank_id转名称,带缓存
function rankName($id)
{
    static $map;
    if (!$map) {
        $map = getMap("SELECT rank_id, rank FROM hr_rank");
    }
    return $map[$id];
}

/**
 * 时间戳转日期,主要用于模板显示日期
 * @example
 * {$r.add_ts|date2}
 * {$r.add_ts|date2='Y-m-d H:i'}
 *
 * @param int $time 时间戳
 * @param string $format 日期格式
 * @return string
 */
function date2($time, $format = 'Y-m-d H:i')
{
    return $time ? date($format, $time) : '';
}

function date3($time, $format = 'Y-m-d')
{
    return $time ? date($format, $time) : '';
}


/**
 * 输出审核状态,0=未审核 1=已审核 2=已拒绝
 * 可在模板里直接使用{$r.st|st}
 * @param int $st
 */
function st($st)
{
    $map = array('未审核', '已审核', '已拒绝');
    return $map[$st];
}

/**
 * 返回部门负责人id
 * 如果自己就是负责人,或者自己是总监,副总,则返回false
 *
 * @param int $member_id
 */
function leader_id($member_id)
{
    $member = M('common_member')->where("member_id = $member_id")->find();
    if (in_array($member['role_id'], array(3, 4))) { //总监/副总
        return false;
    }
    if ($member['role_id'] == 2) {   //经理,判断是否独立部门负责人
        $dep = M('department')->where("leader_id = $member_id AND `type` = 30")->find();
        if ($dep) return false;
    }
    $dep_id = $member['real_dep_id'] ? $member['real_dep_id'] : $member['department_id'];
    $dep    = M('department')->where("id = $dep_id")->find();
    return $dep['leader_id'];
}

//搜索自己之上的总监
function director($member_id)
{
    $pidMap  = M('common_member')->map('member_id', 'pid');
    $roleMap = M('common_member')->map('member_id', 'role_id');
    for ($i = 0; $i <= 7; $i++) {
        $pid = $pidMap[$member_id];
        if (!$pid) return 0;
        $role_id = $roleMap[$pid];
        if ($role_id == 3) return $pid;
        $member_id = $pid;
    }
    return 0;
}

//搜索自己之上的副总
function vice_boss($member_id)
{
    $pidMap  = M('common_member')->map('member_id', 'pid');
    $roleMap = M('common_member')->map('member_id', 'role_id');
    for ($i = 0; $i <= 7; $i++) {
        $pid = $pidMap[$member_id];
        if (!$pid) return 0;
        $role_id = $roleMap[$pid];
        if ($role_id == 4) return $pid;
        $member_id = $pid;
    }
    return 0;
}

/**
 * 返回角色级别
 */
function role_lv($member)
{
    if ($member['member_id'] == 7961) {
        return '总经理';
    }

    if ($member['role_id'] == 4) {
        return '副总经理';
    }
    if ($member['role_id'] == 3) {
        return '总监';
    }
    if ($member['role_id'] == 2) {
        return '经理';
    }

    return '员工';
}

/**
 * 通用条件解析
 *
 * @param string $table         主表名
 * @param string $mod           如果是join模式,普通键值为a表字段,下划线开头的为b表字段
 * @param array $disabledField  禁止用于搜索的字段
 * @return string
 */
function parseWhere($mod = '', $disabledField = array())
{
	if(is_string($disabledField)) {
		$disabledField = explode(',', $disabledField);
		foreach($disabledField as $k => &$s) {
			$s = trim($s);
			if(!$s) unset($disabledField[$k]);
		}
	}
	if (I('post.')) {
		$params = I('post.');
	} else {
		$params = I('get.');
	}
	$where = array();
	foreach ($params as $field => $v) {
		if (!is_array($v)) {
			$v = trim($v);
		}
		if (in_array($field, array('p', 'order', 'prop', 'size'))) continue;
		if ($v === '-1') continue;
		if ($v === '') continue;
		if (strpos($field, '_no_search')) continue;
		$prev = '';
		if ($mod == 'join') {
			if ($field[0] == '_') {
				$prev  = 'b.';
				$field = substr($field, 1, 99);
			} else {
				$prev = 'a.';
			}
		}

		//部门包含下级部门
		if (strpos($field, '_not_in')) {
			$field   = str_replace('_not_in', '', $field);
			$where["{$prev}$field"] = array('not in', $v);
		} else if (strpos($field, '_in')) {
			$field   = str_replace('_in', '', $field);
			$where["{$prev}$field"] = array('in', $v);
		} else if (strpos($field, '_like')) {
			$field   = str_replace('_like', '', $field);
			$where["{$prev}$field"] = array('like', "%$v%");
		} else if (strpos($field, '_lt')) {
			$field   = str_replace('_lt', '', $field);
			$where["{$prev}$field"] = array('lt', $v);
		} else if (strpos($field, '_gt')) {
			$field   = str_replace('_gt', '', $field);
			$where["{$prev}$field"] = array('gt', $v);
		} else if (strpos($field, '_neq')) {
			$field   = str_replace('_neq', '', $field);
			$where["{$prev}$field"] = array('neq', $v);
		} else {
			if ($v == 'null') {
				$where["{$prev}$field"] = array('EXP', 'IS NULL');
			} else if ($v == 'not_null') {
				$where["{$prev}$field"] = array('EXP', 'IS NOT NULL');
			} else {
				$where["{$prev}$field"] = $v;
			}
		}
	}
	foreach ($where as $k => $v) {
		$f = str_replace(array('a.', 'b.'), '', $k);
		if(in_array($f, $disabledField)) unset($where[$k]);
	}
	return $where;
}

//对分类修改进行特殊处理(取整，包含下级）
function cate_where()
{
	if ($_POST['cate_id']) {
		$_POST['cate_id'] = (int) $_POST['cate_id'];
		$cate_id = (int) $_POST['cate_id'];
	}elseif ($_GET['cate_id']) {
		$_GET['cate_id'] = (int) $_GET['cate_id'];
		$cate_id = (int) $_GET['cate_id'];
	}else{
		return;
	}
	$son = M('cate')->where(array('pid' => $cate_id))->col('id');
	if($son) {
		$son_son = M('cate')->where(array('pid' => array('in', $son)))->col('id');
		$son = array_merge($son, $son_son);
	}
	$son[] = $cate_id;
	if(count($son) > 1) {
		if ($_POST['cate_id']) {
			$_POST['cate_id_in'] = $son;
			unset($_POST['cate_id']);
		}else{
			$_GET['cate_id_in'] = implode(',', $son);
			unset($_GET['cate_id']);
		}
	}
}

/**
 * 按照key组合数组
 *
 * @param    array
 * @param    string
 *
 * @return   array
 **/
function arrayGroup($array, $key)
{
    if (empty($array)) {
        return array();
    }

    $array1 = array();

    foreach ($array as $val) {
        $array1[$val[$key]][] = $val;
    }

    return $array1;
}

/**
 * 条形码生成
 * ean13格式、13位数字、是常用商品码格式
 *
 * @param int $code
 * @example 
 * Barcode('6901028055048');
 */
function Barcode($code) 
{
    //一个单元的宽度
    $lw = 2;
    //条码高 
    $hi = 100;
    $Guide = array(1=>'AAAAAA','AABABB','AABBAB','ABAABB','ABBAAB','ABBBAA','ABABAB','ABABBA','ABBABA');
    $Lstart ='101';
    $Lencode = array(
        "A" => array('0001101','0011001','0010011','0111101','0100011','0110001','0101111','0111011','0110111','0001011'),
        "B" => array('0100111','0110011','0011011','0100001','0011101','0111001','0000101','0010001','0001001','0010111')
    );
    $Rencode = array('1110010','1100110','1101100','1000010','1011100', '1001110','1010000','1000100','1001000','1110100');    
    
    $center = '01010';
    
    $ends = '101';
    if(strlen($code) != 13 ){
        die("必须是13位数字");
    }
    
    //校验码检测
    $lsum =0;
    $rsum =0;
    for($i=0; $i<(strlen($code)-1); $i++){
        if($i % 2){
            $lsum +=(int)$code[$i];
        }else{
            $rsum +=(int)$code[$i];
        }
    }
    $tsum = $lsum * 3 + $rsum;
    if($code[12] != (10-($tsum % 10))){
        die("检验码验证错误");
    } 
    
    $barcode = $Lstart;
    for($i=1;$i<=6;$i++){
        $barcode .= $Lencode [$Guide[$code[0]][($i-1)]] [$code[$i]];
    }
    $barcode .= $center;
    
    for($i=7;$i<13;$i++){
        $barcode .= $Rencode[$code[($i)]] ;
    }
    $barcode .= $ends;
    
    $img = ImageCreate($lw*95+60,$hi+30);
    $fg = ImageColorAllocate($img, 0, 0, 0);
    $bg = ImageColorAllocate($img, 255, 255, 255);
    ImageFilledRectangle($img, 0, 0, $lw*95+60, $hi+30, $bg);
    $shift=10;
    for ($x=0;$x<strlen($barcode);$x++) {
        if (($x<4) || ($x>=45 && $x<50) || ($x >=92)){ 
            $sh=10; 
        }else{ 
            $sh=0; 
        }
        if ($barcode[$x] == '1') { 
            $color = $fg;
        }else{ 
            $color = $bg; 
        }
        ImageFilledRectangle($img, ($x*$lw)+30,5,($x+1)*$lw+29,$hi+5+$sh,$color);
    }
    ImageString($img,5,20,$hi+5,$code[0],$fg);
    for ($x=0;$x<6;$x++) {
        ImageString($img,5,$lw*(8+$x*6)+30,$hi+5,$code[$x+1],$fg);
        ImageString($img,5,$lw*(53+$x*6)+30,$hi+5,$code[$x+7],$fg);
    }

    header("Content-Type: image/png");
    ImagePNG($img);
}

//创建token
function create_token($id, $username)
{
    $salt = C('SYNC_LOGIN_KEY');
    $token = md5($id.$username.$salt);
    return $token;
}

//过滤数组
function allow_edit($data, $allow_list)
{
    $row = array();
    foreach ($data as $k => $v) {
        if(in_array($k, $allow_list)) {
            $row[$k] = $v;
        }
    }
    return $row;
}

/**
 * 检验两个数组差异并报错(例如用于导入excel表头的验证)
 * @param $arr1     正确数组
 * @param $arr2     待验证数组
 */
function diff_array($arr1, $arr2)
{
    if($arr1 === $arr2) return true;

    $err = '';
    $diff = array_diff($arr1, $arr2);   //多余字段
    if($diff) {
        $err .= '表头错误，缺少字段：';
        foreach($diff as $k => $v) {
            $err .= $v . ', ';
        }
        $err = substr($err, 0, -2);
        $err .= "<br/>";
    }

    $diff2 = array_diff($arr2, $arr1);  //缺少字段
    if($diff2) {
        $err .= '表头错误，多余字段：';
        foreach($diff2 as $k => $v) {
            $err .= $v . ', ';
        }
        $err = substr($err, 0, -2);
    }
    if($err) return $err;

    //字段顺序错误
    $err = "表头顺序错误，正确顺序为：\n";
    foreach($arr1 as $v) {
        $err .= $v . ', ';
    }
    $err = substr($err, 0, -2);
    return $err;
}

//采用curl代替file_get_contents
function curl_file_get_contents($url){
    if(function_exists('file_get_contents')) {
        $r = file_get_contents($url);
    } else {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $durl);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_USERAGENT, _USERAGENT_);
        curl_setopt($ch, CURLOPT_REFERER,_REFERER_);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $r = curl_exec($ch);
        curl_close($ch);
    }
    return $r;
}

//过滤特殊字符
function fstr($str, $search, $to){
    return str_replace($search, $to, $str);
}

//组合搜索sql
function build_condition($search = []){
    $condition = [];

    if($search['title'])
        $condition[] = " title LIKE '%{$search['title']}%'";

    if($search['real_name'])
        $condition[] = " real_name LIKE '%{$search['real_name']}%'";

    if($search['dep_id']){
        $dep_ids = M('department')->where("id = {$search['dep_id']} or find_in_set({$search['dep_id']},path)")->field('id,name')->col('id');
        $condition[] = " dep_id IN(". implode(',', $dep_ids) .")";
    }


    if($search['cate_id'])
        $condition[] = " cate_id = {$search['cate_id']}";

    if(isset($search['st']))
        $condition[] = " st = {$search['st']}";

    if($search['pro_cate_id'])
        $condition[] = " pro_cate_id = {$search['pro_cate_id']}";

    if($search['pro_id'])
        $condition[] = " pro_id = {$search['pro_id']}";

    if($search['com_id'])
        $condition[] = " com_id = {$search['com_id']}";

    if($search['sg_module']){
        $m = M('sg_wt_module')->where([ 'title' => ['LIKE',"%{$search['sg_module']}%"] ])->field('pro_id')->select();
        $ids = 0;
        if($m) $ids = implode(',', array_column($m, 'pro_id'));

        $condition[] = " id IN ({$ids})";
    }
        

    if($search['dt']){
        $condition[] = " dt = '{$search['dt']}'";
        unset($search['month']);
    }

    if($search['month']){
        $condition[] = " month = '{$search['month']}'";
    }
        
    return $condition ? implode(' AND ', $condition) : '';
}

//更新日志
function json_log($new, $old = '')
{
    if(!$old){
        $old = [];
    } else $old = json_decode($old ,true);

    array_unshift($old, $new);
    return json_encode($old, JSON_UNESCAPED_UNICODE);
}


//获取员工姓名部门
function getDepAndUname($member_id)
{
    return  M('member m')->where("m.id = {$member_id}")->join('department d ON m.department_id = d.id')
            ->field('m.real_name, d.id dep_id, d.name dep_name')->find();
}

//日期格式标准化（主要用于excel中日期格式多种多样）
function format_date($date)
{
    $date = trim($date);
    if(preg_match('#^\d{4}\-\d{1,2}\-\d{1,2}$#', $date)) {  //2018-3-15
        list($m, $d, $y) = explode('-', $date);
        $y = '20'.$y;
    }else if(preg_match('#^\d{1,2}\-\d{1,2}\-\d{2}$#', $date)) {  //02-21-18
        list($m, $d, $y) = explode('-', $date);
        $y = '20'.$y;
    }else if(preg_match('#^\d{4}\/\d{1,2}\/\d{1,2}$#', $date)) {  //2018/1/25
        list($y, $m, $d) = explode('/', $date);
    }else if(preg_match('#^(\d{4})年(\d{1,2})月(\d{1,2})日$#', $date, $rs)) {  //2018年3月15日
        $y = $rs[1];
        $m = $rs[2];
        $d = $rs[3];
    }else{
        return false;
    }
    if(strlen($m) == 1) $m = '0'.$m;
    if(strlen($d) == 1) $d = '0'.$d;
    $date = $y.'-'.$m.'-'.$d;
    return $date;
}


/**
 * 检测模块状态，是否可修改
 * @param $module
 * @param $month
 */
function check_modult_st($module, $month)
{
    $data = M('data')->where(array('month' => $month))->find();
    if(!$data) json(0, '无此月份状态数据'.$month);
    $field = $module.'_st';
    if(!isset($data[$field])) json(0, '模块异常'.$module);
    if($data[$field] == 'pass') {
        json(0, '已审核数据不可修改');
    }
}

/**
 * 价格格式化
 * 四舍五入、保留两位小数、并去除后辍0
 * 如果参数是数组，则对其中所有浮点值进行操作
 * @param   mixed   $value  数值或数组
 * @return mixed    数值或数组
 */
function price($value)
{
    if(is_array($value)) {
        foreach($value as &$v) {
            if(is_numeric($v)) {
                $v = floatval(number_format($v, 2, '.', ''));
            }
        }
    }else{
        $value = floatval(number_format($value, 2, '.', ''));
    }
    return $value;
}

/**
 * 根据数据获取合计信息
 * @param $model    obj     表模型
 * @param $where    string  条件语句
 * @param $fields     array   字段配置,例如array('合计', '', '', '','','wage','shebao','fund','wage1','wage2','wage_offset','');
 *                             按前端表格的字段顺序，不统计的字段为空，显示合计的字段写合计
 * @return mixed
 */
function summary($model, $where, $fields)
{
    $sum = array();
    foreach($fields as $field) {
        if(!$field || $field == '合计') {
            continue;
        }
        $sum[] = "SUM($field) $field";
    }
    $sum = implode(',', $sum);
    $summary = $model->field($sum)->where($where)->find();
    foreach($summary as &$a) {
        $a = price($a);
    }
    //根据字段顺序，将关联数组转为索引数组
    foreach($fields as $k => &$field) {
        if($field != '合计' && $field) $field = $summary[$field];
    }
    return $fields;
}

/**
 * 根据$_POST里的排序参数排序二维数组
 * 像统计报表这种是group by后的数据，直接用sql语句的order by无效，但又要兼容前端的表格排序，所以需要调用这个方法
 * 用法： usort($data, keysort);
 * @param $a
 * @param $b
 * @return int
 */
function keysort($a, $b)
{
    $field = $_POST['prop'];    //排序字段
    if($_POST['order'] == 'descending') {
        return $a[$field] > $b[$field] ? 1 : -1;
    }else{
        return $a[$field] > $b[$field] ? -1 : 1;
    }
}

//从多级数组中提取field值
function getFieldByArray($array, &$fields = array())
{
    foreach($array as $arr) {
        if(isset($arr['field'])) {
            $fields[] = $arr['field'];
            if($lv == 2) echo '增加字段';
        }
        if($arr['children']) {
            getFieldByArray($arr['children'], $fields);
        }
    }
}

//输出片段内容
function section($id)
{
	$section = M('section')->find($id);
	return $section ? $section['content'] : '{无此片段:' . $id . '}';
}